package com.kosinsut.youtubeplaylistbuilder.playlistbuilder;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import com.google.gdata.client.youtube.YouTubeService;
import com.google.gdata.data.PlainTextConstruct;
import com.google.gdata.data.youtube.PlaylistEntry;
import com.google.gdata.data.youtube.PlaylistLinkEntry;
import com.google.gdata.data.youtube.PlaylistLinkFeed;
import com.google.gdata.data.youtube.VideoEntry;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;
import com.kosinsut.youtubeplaylistbuilder.Song;
import com.kosinsut.youtubeplaylistbuilder.songretriever.SongRetriever;
import com.kosinsut.youtubeplaylistbuilder.songretriever.SongRetrieverException;

/**
 * PlaylistBuilder is the main class for YoutubePlaylistBuilder. It will use the account profile to connect to Youtube service, call SongRetriever to get a list of song, and finally create a playlist with all these songs.
 * @author Kosin
 *
 */
public class PlaylistBuilder {

	private AccountProfile accountProfile;
	private SongRetriever songRetriever;
	private VideoSearcher searcher;
	
	public PlaylistBuilder(AccountProfile accountProfile, SongRetriever songRetriever) {
		this.accountProfile = accountProfile;
		this.songRetriever = songRetriever;
		this.searcher = new MVVideoSearcher();
	}
	
	public PlaylistBuilder(AccountProfile accountProfile, SongRetriever songRetriever, VideoSearcher searcher) {
		this.accountProfile = accountProfile;
		this.songRetriever = songRetriever;
		this.searcher = searcher;
	}
	
	/**
	 * Create a Youtube playlist. This method will use SongRetriever supplied when this instance constructed to get a list of song. Then, it will create a playlist on Youtube.com and insert all these songs into the playlist. 
	 * @param playlistName Playlist name you want
	 * @param limit maximum song to be created in the playlist
	 * @return the number of songs created
	 * @throws SongRetrieverException in case songs cannot be retrieved
	 * @throws PlaylistBuilderException in case the playlist cannot be created
	 */
	public int buildYoutubePlaylist(String playlistName, int limit) throws SongRetrieverException, PlaylistBuilderException {
		List<Song> songList = songRetriever.retrieveSongs();
		return buildYoutubePlaylist(playlistName, songList, limit);
		
	}
	
	/**
	 * Create a Youtube playlist. This method create a playlist on Youtube.com and insert all songs into the playlist. 
	 * @param playlistName Playlist name you want
	 * @param songList songs to be inserted into the playlist
	 * @param limit maximum song to be created in the playlist
	 * @return the number of songs created
	 * @throws PlaylistBuilderException in case the playlist cannot be created
	 */
	public int buildYoutubePlaylist(String playlistName, List<Song> songList, int limit) throws PlaylistBuilderException {

		try {
			YouTubeService service = new YouTubeService(accountProfile.getApplicationName(), accountProfile.getDeveloperKey());
			try {
				service.setUserCredentials(accountProfile.getUsername(), accountProfile.getPassword());
			} catch (AuthenticationException e) {
				e.printStackTrace();
				throw new PlaylistBuilderException();
			}
			
			playlistName = playlistName.trim();
			
			String feedUrl = "http://gdata.youtube.com/feeds/api/users/default/playlists";

			PlaylistLinkFeed feed = service.getFeed(new URL(feedUrl), PlaylistLinkFeed.class);

			for(PlaylistLinkEntry entry : feed.getEntries()) {
			  if (entry.getTitle().getPlainText().equalsIgnoreCase(playlistName)) {
				  throw new PlaylistBuilderException("The playlist exists");
			  }
			}

			PlaylistLinkEntry newEntry = new PlaylistLinkEntry();
			newEntry.setTitle(new PlainTextConstruct(playlistName));
			newEntry.setSummary(new PlainTextConstruct("Created by YoutubePlaylistBuilder"));

			PlaylistLinkEntry createdEntry = service.insert(new URL(feedUrl), newEntry);
			String playlistUrl = createdEntry.getFeedUrl();
			URL plUrl = new URL(playlistUrl);
			
			int videoCount = 0;
			for (Song s : songList) {
				try {
					VideoEntry videoEntry = this.searcher.searchVideoEntry(service, s);							
					PlaylistEntry playlistEntry = new PlaylistEntry(videoEntry);
					service.insert(plUrl, playlistEntry);
					System.out.println(videoEntry.getTitle().getPlainText());
					videoCount++;
					if (videoCount >= limit) {
						break;
					}
				} catch (PlaylistBuilderException e) {
					
				}
			}
			return videoCount;

		} catch (MalformedURLException e) {
			e.printStackTrace();
			throw new PlaylistBuilderException("The playlist cannot be created");
		} catch (IOException e) {
			e.printStackTrace();
			throw new PlaylistBuilderException("The playlist cannot be created");
		} catch (ServiceException e) {
			e.printStackTrace();
			throw new PlaylistBuilderException("Youtube service errors");
		}
					
	}	

}
